﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO.Ports;

namespace Terrae.Clases
{
    public class Arduino : Entidad
    {
        #region Atributos

        private string _nombrePuerto;
        private SerialPort _sp;
        private int valor;
        private bool verificarTimer = false;
        private System.Timers.Timer tiempoEspera;
        private Object valorRetornado;

        #endregion Atributos

        #region Constructore

        /// <summary>
        /// Constructor vacio de la clase Arduino.
        /// </summary>
        public Arduino()
        {
        }
        
        public Arduino(string nombreP, int numP = 9600)
        {
            _sp = new SerialPort(nombreP, numP);
        }

        #endregion Constructore

        #region Getters & Setters

        public Object ValorRetornado
        {
            get { return valorRetornado; }
            set { valorRetornado = value; }
        }
        #endregion Getters & Setters

        #region Métodos

        public void RespuestaTimer(object sender, EventArgs e)
        {
            verificarTimer = true;
        }

        public void DigitalWrite(string tipoAccion)
        {
            try
            {
                _sp.Open();
                _sp.Write(tipoAccion);
            }
            catch (Exception ex)
            {
                _sp.Close();
            }
            finally
            {
                _sp.Close();
            }
        }

        public void DigitalRead(string tipoAccion)
        {
            try
            {
                _sp.Open();
                valor = Convert.ToInt32(recibe_cadena());
            }
            catch (TimeoutException ex)
            {
                _sp.Close();
                throw new TimeoutException("Termino el tiempo de ejecución", ex);
            }
            catch (FormatException ex)
            {
                _sp.Close();
                throw new FormatException("No se realizo el casteo correctamente", ex);
            }
            finally
            {
                _sp.Close();
            }
        }

        /// <summary>
        /// escribimos la acción a realizar y
        /// leemos el valor retornado por el puerto serial
        /// </summary>
        /// <param name="tipoAccion"></param>
        public void DigitalReadWrite(string tipoAccion)
        {
            string retorno = "";
            try
            {
                // abrimos la conexión del puerto serial
                _sp.Open();
                // escribimos la acción a tomar en puerto serial
                _sp.Write(tipoAccion);
                // convertirmos la cadena en de byte en int
                retorno = recibe_cadena();
                // verificamo que la lectura sea correcta
                if (retorno.Equals("Read fail") || retorno.Length == 0)
                    ValorRetornado = null;
                else // sino,
                {
                    ValorRetornado = Convert.ToInt32(retorno);
                }
            }
            catch (TimeoutException ex)
            {
                _sp.Close();
                
            }
            catch (FormatException ex)
            {
                _sp.Close();
             
            }
            catch (Exception ex)
            {
                _sp.Close();
              
            }
            finally
            {
                _sp.Close();
            }
        }

        private String recibe_cadena()
        {
            String cadena = "";
            char caracter;
            long i = 0;
            bool verif = true;

            while (_sp.BytesToRead <= 0 )
            {
                //esperamos un tiempo a que manden la cadena
                /*if (i > 999999999999999999)
                {
                    verif = false;
                    break;
                }
                i++;*/
 
            }
            i = 0;

            while (true && verif == true)
            {
                caracter = Convert.ToChar(_sp.ReadByte());

                if ((caracter != '%') && (caracter != '*') && (caracter != '!') && (caracter != '¡'))
                {
                    cadena += caracter;
                }
                else
                {
                    break;
                }
                i++;
            }
            return cadena;
        }

        #endregion Métodos

        #region Getter and Setter

        public string NombrePuerto
        {
            get { return _nombrePuerto; }
            set { _nombrePuerto = value; }
        }

        public SerialPort SP
        {
            get { return _sp; }
            set { _sp = value; }
        }

        #endregion Getter and Setter
    }
}